package com.hp.TrimClient;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.hp.TrimClient.Enums.BaseObjectTypes;
import com.hp.TrimClient.MainObjects.Location;


public class TrimObjectBase extends PropertyFetchBase implements TrimProperty, ServiceObject {
	private BaseObjectTypes TrimType;
	private String StringValue;
	private FieldCollection Fields;	
	private List<MainObjectAction> ActionsToCall;
	private long Uri;
	private transient TrimClient trimClient;
	
	
	public void post() throws Exception {
		this.post(null); 
	}
	
	public void post(File file) throws Exception {
		if (this.trimClient == null) {
			throw new Exception("TrimClient must be set.");
		}
		this.trimClient.postAndUpdate(this, file); 

	}
	
	@Override
	public void setTrimClient(TrimClient trimClient) {
		this.trimClient = trimClient;
		
	}
	
	//@com.hp.TrimClient.DataMember(name="Uri")
	public long getUri() {
		return Uri;
	}
	
	public void setUri(long uri) {
		Uri = uri;
	}

	@Override
	public String getStringValue() {
		return StringValue;
	}

	@Override
	public void setStringValue(String stringValue) {
		this.StringValue = stringValue;
		
	}

	public FieldCollection getFields() {
		return Fields;
	}

	public void setFields(FieldCollection fields) {
		Fields = fields;
	}
	
	public void setCustomField(String name, Location value) {
		initialiseFields();
		
		Fields.put(name, value);
	}
	
	private void initialiseFields() {
		if (Fields == null) {
			Fields = new FieldCollection();
		}		
	}
	
	public void setCustomField(String name, Integer value) {
		initialiseFields();
		
		Fields.put(name, new DefaultTrimProperty<Integer>(value));
	}
	
	public void setCustomField(String name, Long value) {
		initialiseFields();
		
		Fields.put(name, new DefaultTrimProperty<Long>(value));
	}
	
	public void setCustomField(String name, Boolean value) {
		initialiseFields();
		
		Fields.put(name, new DefaultTrimProperty<Boolean>(value));
	}
	
	public void setCustomField(String name, Double value) {
		initialiseFields();
		
		Fields.put(name, new DefaultTrimProperty<Double>(value));
	}
	
	public void setCustomField(String name, String value) {
		initialiseFields();
		
		Fields.put(name, new DefaultTrimProperty<String>(value));
	}
	
	public void setCustomField(String name, Date value) {
		initialiseFields();
		
		Fields.put(name, new TrimDateTime(value));
	}
	
	public String getFieldValueAsString(String name) {
		TrimProperty prop = getField(name);
		if (prop != null) {
			return prop.getStringValue();
		}
		return null;
		
	}
	
	public Object getFieldValue(String name) {
		TrimProperty prop = getField(name);
		if (prop != null) {
			if (prop instanceof DefaultTrimProperty<?>) {
				return ((DefaultTrimProperty<?>)prop).getValue();
			}
			return prop;
		}
		return null;
	}
	
	private TrimProperty getField(String name) {
		if (this.Fields.containsKey(name)) {
			 
			TrimProperty prop = this.Fields.get(name);
			
			return prop;
		}
		return null;
	}

	@Override
	public Class<?> getTrimClass() {
		// TODO Auto-generated method stub
		return this.getClass();
	}
	
	public Map<String, String> membersToMap() {
		
		Map<String, String> map = new HashMap<String, String>();
		
		if (this.getUri() > 0) {
			map.put("Uri", Long.toString(this.getUri()));
		}
		
		try {

			
			for (PropertyDescriptor properytDescriptor : Introspector.getBeanInfo(this.getClass(), Object.class).getPropertyDescriptors()) {
				Method method = properytDescriptor.getReadMethod();

				if(method != null) {
				 Object val = method.invoke(this);
				

				
				if (val != null) {
					Annotation dataMember = method.getAnnotation(DataMember.class);
					if(dataMember instanceof DataMember) {	
						if (val.getClass().isArray()) {
							map.put(((DataMember)dataMember).name(), Arrays.toString((String[])val));
						} else {
							map.put(((DataMember)dataMember).name(), val.toString());
						}
					}

				}
				}
				
				if (this.Fields != null) {
					for (Entry<String, TrimProperty> entry : this.Fields.entrySet()) {
						Object val = this.getFieldValue(entry.getKey());
						map.put(entry.getKey(), val == null ? "" : val.toString());
					}
				}
			}
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException | IntrospectionException e) {
			// TODO Auto-generated catch block
		//	e.printStackTrace();
			
			// do nothing, just return an empty map.
		}
		return map;
	}
	
	
	@Override public String toString() {
		return Long.toString(this.Uri);
	}

	public List<MainObjectAction> getActionsToCall() {
		return ActionsToCall;
	}

	public void setActionsToCall(List<MainObjectAction> actionsToCall) {
		ActionsToCall = actionsToCall;
	}
	
	public void addAction(com.hp.TrimClient.MainObjectAction action) {
		if (ActionsToCall == null) {
			ActionsToCall = new ArrayList<MainObjectAction>();
		}
		ActionsToCall.add(action);
	}

	public BaseObjectTypes getTrimType() {
		return TrimType;
	}

	public void setTrimType(BaseObjectTypes trimType) {
		TrimType = trimType;
	}
}
